package paycenter

import (
	"encoding/json"
	"fmt"
	"strings"

	"gmanager/app/constants"
	"gmanager/app/utils"

	"github.com/gogf/gf/container/gmap"
	"github.com/gogf/gf/container/gvar"
	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gutil"
)

const (
	PAY_TYPE_PAYTM = "3"
	PAY_TYPE_UPI   = "4"
	PAY_TYPE_IMPS  = "7"
)

// Bmartpay下单参数
type BmartpayOrderPay struct {
	ChannelCode     string `json:"channelCode"`     //是	string	-	平台分配给接入方的渠道编号	是
	OutUserId       string `json:"outUserId"`       //是	string	100	接入方用户id	是
	OutOrderNo      string `json:"outOrderNo"`      //是	string	255	接入方订单号	是
	CommodityAmount string `json:"commodityAmount"` //是	string	-	支付金额，币种：INR 示例：“1200.01” 精确到两位小数
	// CommodityId string `json:"commodityId"` //是	string	-	支付金额，币种：INR 示例：“1200.01” 精确到两位小数
	Name   string `json:"-"` //是	string	20	用户姓名	否
	Email  string `json:"-"` //是	string	255	收款人邮箱，格式xxx@xxx.xxx	否
	Mobile string `json:"-"` //是	string	20	收款人手机，格式10位数字,不带地区码+91	否
	Sign   string `json:"-"` //是	string	string	md5签名，签名算法请参考签名（章节0）	否
}

// Bmartpay下单参数
type BmartpayOrderDraw struct {
	OutOrderNo   string `json:"outOrderNo"`  //是	string	255	接入方订单号	是
	OutUserId    string `json:"outUserId"`   //是	string	100	接入方用户ID	是
	ChannelCode  string `json:"channelCode"` //是	string	-	平台分配渠道编号， 请联系平台获取	是
	PayType      string `json:"payType"`     //是	integer	1	付款类型 见下表	是
	PayAccount   string `json:"payAccount"`  //是	string	255	跟付款类型对应的收款账号，格式见下表	是
	PayAmount    string `json:"payAmount"`   //是	double	0.00	付款金额，单位印度卢比，可带2位小数	是
	AccountOwner string `json:"-"`           //是	string	50	收款人姓名，payType为4,7时必传	否
	BankCode     string `json:"-"`           //否	string	100	ifsc payType为7时必传	否
	Email        string `json:"-"`           //是	string	100	收款人邮箱，格式xxx@xxx.xxx	否
	Mobile       string `json:"-"`           //是	string	20	收款人手机，格式10位数字,不带地区码+91	否
	ServerNotify string `json:"-"`           //否	string	255	代付完成后通知地址，传了此参数则通知到参数传入的地址中，未传则通知应用配置中的地址	否
	Sign         string `json:"-"`           //是	string	-	md5签名，签名算法请参考签名（章节0）	否
}

type Bmartpay struct {
	ID   int
	Name string
	Conf *gjson.Json
}

func (self *Bmartpay) GetID() int {
	return self.ID
}
func (self *Bmartpay) GetName() string {
	return self.Name
}

func (self *Bmartpay) GetNotifyURL(payType string) string {
	return "/api/v1/" + gconv.String(self.ID) + "/" + payType + "/notify"
}

// 支付下单
func (self *Bmartpay) GetPayOrder(order g.Map, r *ghttp.Request) {
	// 用户自身填写的参数内容
	userFields, _ := GetUserFields(gconv.Int(order["user_id"]))
	// 准备参数
	sendOrder := BmartpayOrderPay{
		ChannelCode:     gconv.String(self.Conf.Get("channelCode")),
		OutUserId:       gconv.String(order["uid"]),
		OutOrderNo:      gconv.String(order["order_id"]),
		CommodityAmount: utils.GetPoint(gconv.Float64(order["money"])),
		// CommodityId: "INR20",
		Name:   GetUserField(userFields, "name"),
		Email:  GetUserField(userFields, "email"),
		Mobile: GetUserField(userFields, "mobile"),
		Sign:   gconv.String(self.Conf.Get("sign")),
	}

	// 加密步骤
	// 原串
	signstr, _ := json.Marshal(sendOrder)
	m := gmap.NewTreeMap(gutil.ComparatorString)
	json.Unmarshal(signstr, &m)
	var ostr []string
	for _, field := range m.Keys() {
		ostr = append(ostr, fmt.Sprint(field, "=", m.Get(field)))
	}
	originstr := strings.Join(ostr, "&") + "&key=" + sendOrder.Sign
	g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】下单原串：" + originstr)

	// 加密串
	md5sign, _ := gmd5.EncryptString(originstr)
	j := gjson.New(nil)
	j.Set("channelCode", sendOrder.ChannelCode)
	j.Set("commodityAmount", sendOrder.CommodityAmount)
	j.Set("outOrderNo", sendOrder.OutOrderNo)
	j.Set("outUserId", sendOrder.OutUserId)
	j.Set("sign", md5sign)
	j.Set("name", sendOrder.Name)
	j.Set("email", sendOrder.Email)
	j.Set("mobile", sendOrder.Mobile)
	g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】加密后的串：" + j.MustToJsonString())

	// 发送数据,得到结果
	resp, err := ghttp.Post(
		self.Conf.GetString("url"),
		j.MustToJsonString(),
	)
	// 发送返回异常数据,记录下来
	if err != nil {
		g.DB().Table("game_order").Data(g.Map{
			"app_id":       order["app_id"],
			"uid":          order["uid"],
			"shop_id":      order["shop_id"],
			"money":        order["money"],
			"real_money":   0,
			"conf_id":      self.GetID(),
			"name":         self.GetName(),
			"order_id":     order["order_id"],
			"out_order_id": "",
			"pay_mode":     constants.PAY_MODE_PAY,
			"msg":          "请求三方通道出错：" + err.Error(),
			"status":       constants.ORDER_STATE_PENDING,
		}).Insert()
		g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】请求三方通道失败：" + resp.ReadAllString())
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err.Error(),
		})

	}
	defer resp.Close()
	respStr := resp.ReadAllString()
	g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】请求三方通道成功：" + respStr)

	// 保存下单结果
	respJson, err := gjson.DecodeToJson(respStr)
	if err != nil {
		g.DB().Table("game_order").Data(g.Map{
			"app_id":         order["app_id"],
			"uid":            order["uid"],
			"shop_id":        order["shop_id"],
			"money":          order["money"],
			"real_money":     0,
			"conf_id":        self.GetID(),
			"name":           self.GetName(),
			"order_id":       order["order_id"],
			"out_order_id":   "",
			"pay_mode":       constants.PAY_MODE_PAY,
			"msg":            "请求三方通道成功，但是解析返回的json出错：" + err.Error(),
			"status":         constants.ORDER_STATE_FAIL,
			"order_response": respStr,
		}).Insert()
		g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】请求三方通道成功，解析返回json失败：" + respStr)

		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err.Error(),
		})
	}
	// 验证订单是否成功
	if respJson.GetString("code") == "0" && respJson.GetString("msg") == "success" {
		g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】处理成功：" + respStr)
		g.DB().Table("game_order").Data(g.Map{
			"app_id":         order["app_id"],
			"uid":            order["uid"],
			"shop_id":        order["shop_id"],
			"money":          order["money"],
			"real_money":     0,
			"conf_id":        self.GetID(),
			"name":           self.GetName(),
			"order_id":       order["order_id"],
			"out_order_id":   respJson.GetString("data.orderId"),
			"pay_mode":       constants.PAY_MODE_PAY,
			"msg":            "请求三方通道成功，解析返回json成功，返回跳转url",
			"status":         constants.ORDER_STATE_PENDING,
			"order_response": respStr,
		}).Insert()
		// r.Response.RedirectTo(gconv.String(respJson.Get("data.jumpUrl")))
		r.Response.WriteJsonExit(g.Map{
			"code": 0,
			"msg":  "success",
			"data": g.Map{
				"url": gconv.String(respJson.Get("data.jumpUrl")),
			},
		})

	} else {
		g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】处理失败：" + respStr)
		g.DB().Table("game_order").Data(g.Map{
			"app_id":         order["app_id"],
			"uid":            order["uid"],
			"shop_id":        order["shop_id"],
			"money":          order["money"],
			"real_money":     0,
			"conf_id":        self.GetID(),
			"name":           self.GetName(),
			"order_id":       order["order_id"],
			"out_order_id":   "",
			"pay_mode":       constants.PAY_MODE_PAY,
			"msg":            respStr,
			"status":         constants.ORDER_STATE_FAIL,
			"order_response": respStr,
		}).Insert()
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  "Get order failure",
		})
	}

}

// 支付下单回调
func (self *Bmartpay) NotifyPay(r *ghttp.Request) {
	g.Log("pay").Cat(self.GetName()).Info("【支付回调】【" + r.GetFormString("orderId") + "】数据：" + r.GetBodyString())

	// 获取回调请求里的参数
	amount := r.GetFormString("amount")
	currency := r.GetFormString("currency")
	code := r.GetFormString("code")
	orderId := r.GetFormString("orderId")
	merchantId := r.GetFormString("merchantId")
	appId := r.GetFormString("appId")
	outUserId := r.GetFormString("outUserId")
	passageTradeNo := r.GetFormString("passageTradeNo")
	successTime := r.GetFormString("successTime")
	// commodityId := r.GetFormString("commodityId")
	// outOrderNo := r.GetFormString("outOrderNo")
	// outPayAmount := r.GetFormString("outPayAmount")
	// exchangeRate := r.GetFormString("exchangeRate")
	// amountDollar := r.GetFormString("amountDollar")
	// realAmount := r.GetFormString("realAmount")
	// channelCode := r.GetFormString("channelCode")
	sign := r.GetFormString("sign")

	// 准备参数，拼接获得sign
	m := gmap.NewTreeMap(gutil.ComparatorString)
	m.Set("amount", amount)
	m.Set("currency", currency)
	m.Set("code", code)
	m.Set("orderId", orderId)
	m.Set("merchantId", merchantId)
	m.Set("appId", appId)
	m.Set("outUserId", outUserId)
	m.Set("passageTradeNo", passageTradeNo)
	m.Set("successTime", successTime)

	// 拼接sign
	var ostr []string
	for _, field := range m.Keys() {
		ostr = append(ostr, fmt.Sprint(field, "=", m.Get(field)))
	}
	originstr := strings.Join(ostr, "&") + "&key=" + self.Conf.GetString("sign")
	g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】下单原串：" + originstr)
	// 加密串
	md5sign, _ := gmd5.EncryptString(originstr)

	// 验证加密串
	if md5sign != sign {
		g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】签名串不一致：推送串[" + sign + "],加密串[" + md5sign + "]")
		r.Response.WriteExit("Sign error")
	}
	// g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】签名串一致：推送串[" + sign + "],加密串[" + md5sign + "]")

	if tx, err := g.DB().Begin(); err == nil {
		// 查询数据库是否存在订单,上锁读
		order, err := tx.Table("game_order").Where("out_order_id", orderId).Where("status", constants.ORDER_STATE_PENDING).LockUpdate().One()
		if err != nil {
			tx.Rollback()
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】查询订单数据库出错了：" + err.Error())
			r.Response.WriteExit("Out_order_id error")
		}
		if order == nil {
			tx.Rollback()
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】查询订单数据库找不到或者订单状态已变更")
			r.Response.WriteExit("Out_order_id not found")
		}

		// 更新订单
		_, err = tx.Table("game_order").Where("out_order_id", orderId).Data(g.Map{
			"status":         constants.ORDER_STATE_SUCCESS,
			"real_money":     amount,
			"currency":       currency,
			"notify_request": r.GetBodyString(),
		}).Update()
		// 更新报错处理
		if err != nil {
			tx.Rollback()
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】事务提交该订单时报错了" + err.Error())
			r.Response.WriteExit("Out_order_id update error")
		}
		// 首充更新
		var firstRechargeDiscount *gvar.Var
		var bonusMoney float64 = 0
		isChargeResult, err := tx.Table("user").Where("id", order["uid"]).Data(g.Map{
			"is_charge": 1,
		}).Update()
		isChargeRows, err := isChargeResult.RowsAffected()
		if isChargeRows > 0 {
			firstRechargeDiscount = utils.GetSystemConfigByKey(utils.GetSystemConfig("game_pay"), "first_recharge_discount")
			bonusMoney = gconv.Float64(amount) * (firstRechargeDiscount.Float64() / 100)
		}

		// 提交事务
		err = tx.Commit()
		if err != nil {
			// 出错了,此处查看数据库的状态,看看事务提交是否成功了
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】特别注意!!!事务提交了,但是返回报错了,此时不知道订单时什么状态!!!" + err.Error())
			r.Response.WriteExit("Out_order_id commit error")
		}
		// 推送数据到游戏服务器
		if utils.PushChangeUserMoney(order["uid"].Int(), gconv.Float64(amount)+gconv.Float64(bonusMoney), gconv.Float64(bonusMoney)) {
			utils.PushNotify([]int{order["uid"].Int()}, 0, "", constants.NOTIFY_TYPE_RECHARGE)
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】成功")

		} else {
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】推送给redis失败")
		}

		r.Response.WriteExit("success")

	} else {
		g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】打开事务失败了" + err.Error())
		r.Response.WriteExit("Out_order_id begin error")
	}
}

// 提现下单
func (self *Bmartpay) GetDrawOrder(order gdb.Record, r *ghttp.Request) {
	// 用户自身填写的参数内容
	userFields, _ := GetUserFields(order["uid"].Int())
	// 准备参数
	sendOrder := BmartpayOrderDraw{
		OutOrderNo:  gconv.String(order["order_id"]),
		OutUserId:   gconv.String(order["uid"]),
		ChannelCode: self.Conf.GetString("channelCode"),
		// PayType:     self.Conf.GetString("draw_payType"),
		// PayAccount:  GetUserField(userFields, "")
		// PayAmount: utils.GetPoint(order["money"].Float64() - order["fee"].Float64()),
		PayAmount: utils.GetPoint(order["money"].Float64()),
		// CommodityId: "INR20",
		// Name:   order["uid"].String(),
		// Email:  gconv.String(self.Conf.Get("Email")),
		// Mobile: gconv.String(self.Conf.Get("Mobile")),
		// ServerNotify: fmt.Sprintf("http://%s%s/api/v1/%d/draw/notify", r.GetHost(), g.Cfg().GetString("server.Address"), self.GetID()),
		Sign: self.Conf.GetString("sign"),
	}
	if order["channel_name"].String() == "paytm" {
		sendOrder.PayType = PAY_TYPE_PAYTM
		sendOrder.PayAccount = GetUserField(userFields, "mobile")
	} else if order["channel_name"].String() == "upi" {
		sendOrder.PayType = PAY_TYPE_UPI
		sendOrder.AccountOwner = GetUserField(userFields, "accountOwner")
	} else if order["channel_name"].String() == "imps" {
		sendOrder.PayType = PAY_TYPE_IMPS
		sendOrder.AccountOwner = GetUserField(userFields, "accountOwner")
		sendOrder.BankCode = GetUserField(userFields, "bankCode")
	} else {
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  "Payement channel error",
		})
	}
	sendOrder.Email = GetUserField(userFields, "email")
	sendOrder.Mobile = GetUserField(userFields, "mobile")

	// 加密步骤
	// 原串
	signstr, _ := json.Marshal(sendOrder)
	m := gmap.NewTreeMap(gutil.ComparatorString)
	json.Unmarshal(signstr, &m)
	var ostr []string
	for _, field := range m.Keys() {
		ostr = append(ostr, fmt.Sprint(field, "=", m.Get(field)))
	}
	originstr := strings.Join(ostr, "&") + "&key=" + sendOrder.Sign
	g.Log("pay").Cat(self.GetName()).Info("【代付下单】【" + sendOrder.OutOrderNo + "】下单原串：" + originstr)

	// 加密串
	md5sign, _ := gmd5.EncryptString(originstr)
	j := gjson.New(nil)
	j.Set("outOrderNo", sendOrder.OutOrderNo)
	j.Set("outUserId", sendOrder.OutUserId)
	j.Set("channelCode", sendOrder.ChannelCode)
	j.Set("payType", sendOrder.PayType)
	j.Set("payAccount", sendOrder.PayAccount)
	j.Set("payAmount", sendOrder.PayAmount)
	j.Set("accountOwner", sendOrder.AccountOwner)
	j.Set("bankCode", sendOrder.BankCode)
	j.Set("email", sendOrder.Email)
	j.Set("mobile", sendOrder.Mobile)
	j.Set("serverNotify", sendOrder.ServerNotify)
	j.Set("sign", md5sign)

	g.Log("pay").Cat(self.GetName()).Info("【代付下单】【" + sendOrder.OutOrderNo + "】加密后的串：" + md5sign)
	g.Log("pay").Cat(self.GetName()).Info("【代付下单】【" + sendOrder.OutOrderNo + "】准备发送的数据：" + j.MustToJsonString())
	// postData := g.Map{
	// 	"outOrderNo":   sendOrder.OutOrderNo,
	// 	"outUserId":    sendOrder.OutUserId,
	// 	"channelCode":  sendOrder.ChannelCode,
	// 	"payType":      sendOrder.PayType,
	// 	"payAccount":   sendOrder.PayAccount,
	// 	"payAmount":    sendOrder.PayAmount,
	// 	"accountOwner": sendOrder.AccountOwner,
	// 	"bankCode":     sendOrder.BankCode,
	// 	"email":        sendOrder.PayAccount,
	// 	"mobile":       sendOrder.Mobile,
	// 	"serverNotify": fmt.Sprintf("http://%s/api/v1/%d/draw/notify", r.GetHost(), self.GetID()),
	// 	"sign":         md5sign,
	// }
	// 发送数据,得到结果
	resp, err := ghttp.Post(
		self.Conf.GetString("draw_url"),
		j.MustToJsonString(),
	)

	// 发送返回异常数据,记录下来
	if err != nil {
		g.DB().Table("game_order").Data(g.Map{
			"conf_id":       self.GetID(),
			"name":          self.GetName(),
			"order_request": j.MustToJsonString(),
			"msg":           "请求三方通道出错：" + err.Error(),
		}).Where("id", order["id"]).Update()
		g.Log("pay").Cat(self.GetName()).Info("【代付下单】【" + sendOrder.OutOrderNo + "】请求三方通道失败：" + resp.ReadAllString())
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err.Error(),
		})

	}
	defer resp.Close()
	respStr := resp.ReadAllString()
	//respStr := `{"code":"0","msg":"success","data":{"payAmount":104.50,"payAccount":"","outOrderNo":"92012230207165037818","transOrderId":"202012230229133946322109"}}`
	g.Log("pay").Cat(self.GetName()).Info("【代付下单】【" + sendOrder.OutOrderNo + "】请求三方通道成功：" + respStr)

	// 保存下单结果
	respJson, err := gjson.DecodeToJson(respStr)
	if err != nil {
		g.DB().Table("game_order").Data(g.Map{
			"conf_id":        self.GetID(),
			"name":           self.GetName(),
			"order_request":  j.MustToJsonString(),
			"order_response": respStr,
			"msg":            "请求三方通道成功，解析返回json失败：" + respStr,
		}).Where("id", order["id"]).Update()
		g.Log("pay").Cat(self.GetName()).Info("【代付下单】【" + sendOrder.OutOrderNo + "】请求三方通道成功，解析返回json失败：" + respStr)

		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err.Error(),
		})
	}
	// 验证订单是否成功
	if respJson.GetString("code") == "0" && respJson.GetString("msg") == "success" {
		g.Log("pay").Cat(self.GetName()).Info("【代付下单】【" + sendOrder.OutOrderNo + "】处理成功：" + respStr)
		g.DB().Table("game_order").Data(g.Map{
			"conf_id":        self.GetID(),
			"name":           self.GetName(),
			"out_order_id":   gconv.String(respJson.GetString("data.transOrderId")),
			"msg":            "代付下单成功，等待三方回调",
			"status":         constants.ORDER_STATE_PENDING,
			"order_request":  j.MustToJsonString(),
			"order_response": respStr,
		}).Where("id", order["id"]).Update()
		r.Response.WriteJsonExit(g.Map{
			"code": 0,
			"msg":  "success",
		})
	} else {
		g.Log("pay").Cat(self.GetName()).Info("【支付下单】【" + sendOrder.OutOrderNo + "】处理失败：" + respStr)
		g.DB().Table("game_order").Data(g.Map{
			"conf_id":        self.GetID(),
			"name":           self.GetName(),
			"msg":            "代付下单返回失败：" + respStr,
			"status":         constants.ORDER_STATE_FAIL,
			"order_request":  j.MustToJsonString(),
			"order_response": respStr,
		}).Where("id", order["id"]).Update()
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  "Get order failure",
		})
	}
}

// 提现下单回调
func (self *Bmartpay) NotifyDraw(r *ghttp.Request) {
	g.Log("pay").Cat(self.GetName()).Info("【代付回调】【" + r.GetFormString("orderId") + "】数据：" + r.GetBodyString())

	code := r.GetFormString("code")
	amount := r.GetFormString("amount")
	realAmount := r.GetFormString("realAmount")
	currency := r.GetFormString("currency")
	outUserId := r.GetFormString("outUserId")
	payAccount := r.GetFormString("payAccount")
	outOrderNo := r.GetFormString("outOrderNo")
	orderId := r.GetFormString("orderId")
	merchantId := r.GetFormString("merchantId")
	appId := r.GetFormString("appId")
	successTime := r.GetFormString("successTime")
	sign := r.GetFormString("sign")
	// notifyParam := r.GetFormString("notifyParam")
	// failMessage := r.GetFormString("failMessage")

	// 准备参数，拼接获得sign
	m := gmap.NewTreeMap(gutil.ComparatorString)
	m.Set("code", code)
	m.Set("amount", amount)
	m.Set("realAmount", realAmount)
	m.Set("currency", currency)
	m.Set("outUserId", outUserId)
	m.Set("payAccount", payAccount)
	m.Set("outOrderNo", outOrderNo)
	m.Set("orderId", orderId)
	m.Set("merchantId", merchantId)
	m.Set("appId", appId)
	m.Set("successTime", successTime)
	// m.Set("notifyParam", notifyParam)
	// m.Set("failMessage", failMessage)

	var ostr []string
	for _, field := range m.Keys() {
		ostr = append(ostr, fmt.Sprint(field, "=", m.Get(field)))
	}
	originstr := strings.Join(ostr, "&") + "&key=" + self.Conf.GetString("sign")
	g.Log("pay").Cat(self.GetName()).Info("【代付回调】【通道订单号:" + outOrderNo + "】下单原串：" + originstr)
	// 加密串
	md5sign, _ := gmd5.EncryptString(originstr)

	// 验证加密串
	if md5sign != sign {
		g.Log("pay").Cat(self.GetName()).Info("【代付回调】【通道订单号:" + outOrderNo + "】签名串不一致：推送串[" + originstr + "],加密串[" + md5sign + "]")
		r.Response.WriteExit("Sign error")
	}

	if tx, err := g.DB().Begin(); err == nil {
		// 查询数据库是否存在订单,上锁读
		order, err := tx.Table("game_order").Where("out_order_id", orderId).Where("order_id", outOrderNo).Where("status", constants.ORDER_STATE_PENDING).LockUpdate().One()
		if err != nil {
			tx.Rollback()
			g.Log("pay").Cat(self.GetName()).Info("【代付回调】【通道订单号:" + orderId + "】查询订单数据库出错了：" + err.Error())
			r.Response.WriteExit("Out_order_id error")
		}
		if order == nil {
			tx.Rollback()
			g.Log("pay").Cat(self.GetName()).Info("【代付回调】【通道订单号:" + orderId + "】查询订单数据库找不到或者订单状态已变更")
			r.Response.WriteExit("Out_order_id not found")
		}

		// 更新订单
		_, err = tx.Table("game_order").Where("out_order_id", orderId).Where("order_id", outOrderNo).Data(g.Map{
			"status":         constants.ORDER_STATE_SUCCESS,
			"real_money":     realAmount,
			"currency":       currency,
			"notify_request": r.GetBodyString(),
		}).Update()
		// 更新报错处理
		if err != nil {
			tx.Rollback()
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】事务提交该订单时报错了" + err.Error())
			r.Response.WriteExit("Out_order_id update error")
		}

		// 提交事务
		err = tx.Commit()
		if err != nil {
			// 出错了,此处查看数据库的状态,看看事务提交是否成功了
			g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】特别注意!!!事务提交了,但是返回报错了,此时不知道订单时什么状态!!!" + err.Error())
			r.Response.WriteExit("Out_order_id commit error")
		}

		// 推送给redis
		// if utils.PushNotify([]int{order["uid"].Int()}, 0, "", constants.NOTIFY_TYPE_RECHARGE) == false {
		// 记录推送结果
		// g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】推送给redis失败")
		// }

		r.Response.WriteExit("success")

	} else {
		g.Log("pay").Cat(self.GetName()).Info("【支付回调】【通道订单号:" + orderId + "】打开事务失败了" + err.Error())
		r.Response.WriteExit("Out_order_id begin error")
	}
}

// 查询订单
func (self *Bmartpay) GetQuery(record gdb.Record) (*gmap.Map, error) {

	return gmap.New(true), nil
}

// 查询提现余额
func (self *Bmartpay) GetBalance() (g.List, error) {

	return nil, nil
}
